/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package memoriavirtual;

import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Pedro Freitas
 */
public class LRU implements PoliticaDeSubstituicao {

    public LRU(){
        
    }
    
    @Override
    public void executa(Pagina pagina, MemoriaVirtual mv, ArrayList<Processo> processos, boolean ehEscopoLocal, int momentoAtual, char tipoInstrucao) {
        MemoriaPrincipal mp = mv.getMemoriaPrincipal();
        MemoriaSecundaria ms = mv.getMemoriaSecundaria();
        HashMap<String, TP> processos_TP = mv.getMemoriaPrincipal().getProcessos_TP();

        if (ehEscopoLocal) {
            Processo p = processos.get(0);      // pega o processo daquela tp

            Pagina[] paginas = p.getPaginas();  //pega paginas daquele processo
             
            String nomeProc = p.getNome();      // pega o nome desse processo

            TP tp = processos_TP.get(nomeProc);      // pega tp desse processo

            CelulaTP[] celulas = tp.getCelulas();       // pega celulas dessa tp

            CelulaTP celula = null;     // celula da pagina a ser inserida na mp                       

            for (int i = 0; i < celulas.length; i++) {
                if (celulas[i].getNumPg() == pagina.getNumero()) {
                    celula = celulas[i];                   // pega a celula da pagina a ser inserida na mp
                }
            }

            int indiceMenorReferencia = buscaMenorReferencia(paginas, celulas);

            Pagina paginaSubstituida = null;

            pagina.setMomentoCarga(momentoAtual);
            pagina.setMomentoReferencia(momentoAtual);
            
            p.atualizaPagina(pagina.getNumero(), momentoAtual, momentoAtual);

            celula.setP();
            if(tipoInstrucao == 'W')    celula.setM();            
            tp.atualizaCelulaTP(pagina.getNumero(), tipoInstrucao);        // atualiza celula da TP

            
            
            int index = celulas[indiceMenorReferencia].getNumQuadro();
            Quadro quadro = mp.getQuadro(index);
            quadro.setPagina(pagina);               // troca a pagina alocada naquele quadro da mp
            mp.setQuadro(quadro, index);

            for (int j = 0; j < paginas.length; j++) {
                if (paginas[j].getNumero() == celulas[indiceMenorReferencia].getNumPg()) {
                    paginaSubstituida = paginas[j];
                }

            }

           paginaSubstituida.setMomentoReferencia(momentoAtual);
           p.atualizaPagina(pagina.getNumero(), momentoAtual, momentoAtual);
            
            celulas[indiceMenorReferencia].setP();            
            tp.atualizaCelulaTP2(indiceMenorReferencia);            //atualiza celula da TP        
           
            
        } else {          
            String nomeProcInsere = pagina.getNomeProc();      // pega o nome do processo da pag a ser inserida
                    
            TP tpInsere = processos_TP.get(nomeProcInsere);      // pega tp do processo da pag a será inserida

            CelulaTP[] celulasInsere = tpInsere.getCelulas();       // pega celulas dessa tp
            
            CelulaTP celula = null;    // celula da pagina a ser inserida na mp  
                                 
            
            for (int i = 0; i < celulasInsere.length; i++) {
                if (celulasInsere[i].getNumPg() == pagina.getNumero()) {
                    celula = celulasInsere[i];                   // pega a celula da pagina a ser inserida na mp
                }
            }            
                                 
            
            int indiceMenorReferenciaGlobal = 0;       
            
            
            Processo processo = null;      // processo da pagina a ser inserida
            
            CelulaTP[] celulas = null; 
            
            TP tp = null;
            
            for (int i = 0; i < processos.size(); i++) {

                Processo pAtual = processos.get(i);      // pega o processo 

                Pagina[] paginasAtual = pAtual.getPaginas();  //pega paginas daquele processo

                String nomeProcAtual = pAtual.getNome();      // pega o nome desse processo

                TP tpAtual = processos_TP.get(nomeProcAtual);      // pega tp desse processo

                CelulaTP[] celulasAtual = tpAtual.getCelulas();       // pega celulas dessa tp

                if (buscaMenorReferencia(paginasAtual, celulas) < indiceMenorReferenciaGlobal) {
                    indiceMenorReferenciaGlobal = buscaMenorReferencia(paginasAtual, celulas);
                    processo = pAtual;
                    celulas = celulasAtual;
                    tp = tpAtual;
                    
                }
            }            
            

            
            Pagina paginaSubstituida = null;

            pagina.setMomentoCarga(momentoAtual);
            pagina.setMomentoReferencia(momentoAtual);

            processo.atualizaPagina(pagina.getNumero(), momentoAtual, momentoAtual);


            celula.setP();            
            if(tipoInstrucao == 'W')    celula.setM();            
            tpInsere.atualizaCelulaTP(pagina.getNumero(), tipoInstrucao);        // atualiza celula da TP da pagina q sera inserida

            


            int index = celulas[indiceMenorReferenciaGlobal].getNumQuadro();
            Quadro quadro = mp.getQuadro(index);
            quadro.setPagina(pagina);               // troca a pagina alocada naquele quadro da mp
            mp.setQuadro(quadro, index);
            

            for (int j = 0; j < processo.getPaginas().length; j++) {
                
                if (processo.getPaginas()[j].getNumero() == celulas[indiceMenorReferenciaGlobal].getNumPg()) {
                    paginaSubstituida = processo.getPaginas()[j];
                }

            }

            paginaSubstituida.setMomentoReferencia(momentoAtual);

            celulas[indiceMenorReferenciaGlobal].setP(); 
            tp.atualizaCelulaTP2(indiceMenorReferenciaGlobal);            //atualiza celula da TP 


            
        
        }

    }

    public int buscaMenorReferencia(Pagina[] paginas, CelulaTP[] celulas) {
        int celulaMenorReferencia = 0;
        for (int i = 0; i < celulas.length; i++) {
            int paginaAtual = celulas[i].getNumPg();
            int paginaMenor = celulas[celulaMenorReferencia].getNumPg();
            if ((paginas[paginaAtual].getMomentoReferencia() < paginas[paginaMenor].getMomentoReferencia()) && (celulas[i].isP())) {
                celulaMenorReferencia = i;
            }
        }
        return celulaMenorReferencia;
    }

//    public void buscaMenorRefGlobal(ArrayList<Processo> processos, ArrayList<Pagina> paginas, CelulaTP[] celulas) {
//        int[][] indiceReferencia;
//        indiceReferencia = new int[processos.size()][2];
//
//        // monta uma tabela com os valores de celula e momento de cada processo
//        for (int i = 0; i < indiceReferencia.length; i++) {
//            // colocar a tabela tp referente ao processo AQUI
//            
//            // busca celula com a pagina de menor referencia e salva na tabela a celula e a pagina
//            indiceReferencia[i][0] = buscaMenorReferencia(paginas,celulas);
//            
//            int numPaginaMenorRef = celulas[indiceReferencia[i][0]].getNumPg();
//            indiceReferencia[i][1] = paginas.get(numPaginaMenorRef).getMomentoReferencia();
//        }
//        
//        // começa a busca pela menor referencia global
//        int indiceMenorRefGlobal = 0; 
//        for (int i = 0; i < indiceReferencia.length; i++){
//            if (indiceReferencia[i][1] < indiceReferencia[indiceMenorRefGlobal][1]){
//                indiceMenorRefGlobal = i;
//            }
//        }
//        // aqui temos o numero do processo de menor referencia global
//        // na variavel indiceMenorRefGlobal
//    }    
    
    
}
